<template>
  <div class="graph-container">
    <!-- 页面头部 -->
    <a-card class="header-card" :bordered="false">
      <a-space :size="16" align="center" style="margin-bottom: 16px;">
        <a-avatar :size="48" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%)">
          <template #icon>
            <ApartmentOutlined />
          </template>
        </a-avatar>
        <div>
        <div class="page-title">专利图谱分析</div>
        <div class="page-subtitle">可视化展示专利关系网络</div>
        </div>
      </a-space>
      
      <a-space :size="12" wrap>
        <!-- 核心专利信息提示 -->
        <a-tag v-if="corePatentId" color="purple" style="font-size: 14px; padding: 6px 12px;">
          核心专利ID: {{ corePatentId }}
        </a-tag>
        
        <!-- 选择/切换专利按钮 -->
        <a-button size="large" @click="goToPatentManage">
          <template #icon><EyeOutlined /></template>
          {{ corePatentId ? '切换核心专利' : '选择核心专利' }}
        </a-button>
        
        <!-- 关联类型选择 -->
        <a-select v-model:value="relationType" style="width: 160px;" size="large">
          <a-select-option value="institution">申请机构关联</a-select-option>
          <a-select-option value="inventor">发明人关联</a-select-option>
          <a-select-option value="ipc">IPC分类关联</a-select-option>
          <a-select-option value="technology">技术领域关联</a-select-option>
        </a-select>
        
        <a-button type="primary" size="large" @click="loadGraphData" :loading="loading">
          <template #icon><ReloadOutlined /></template>
          {{ loading ? '加载中...' : '加载数据' }}
          </a-button>
        
        <a-button size="large" @click="toggleFullscreen">
          <template #icon><FullscreenOutlined v-if="!isFullscreen" /><FullscreenExitOutlined v-else /></template>
          {{ isFullscreen ? '退出全屏' : '全屏显示' }}
          </a-button>
        
        <a-button size="large" @click="exportImage">
          <template #icon><CameraOutlined /></template>
            导出图片
          </a-button>
        </a-space>
    </a-card>

    <!-- 图谱展示区域 -->
    <div class="graph-main" :class="{ 'fullscreen': isFullscreen }">
      <a-row :gutter="16">
        <!-- 左侧图谱 -->
        <a-col :span="selectedNode ? 17 : 24">
          <a-card class="graph-card" :bordered="false">
      <template #title>
        <a-space>
          <ClusterOutlined style="font-size: 18px; color: #1890ff;" />
          <span style="font-size: 16px; font-weight: 600;">专利关系图谱</span>
                <a-tag color="blue" v-if="graphData.nodes.length > 0">
                  {{ graphData.nodes.length }} 个节点 / {{ graphData.links.length }} 条关系
                </a-tag>
        </a-space>
      </template>

            <div class="graph-content" ref="graphContainer" id="graph-chart" @contextmenu.prevent></div>
          </a-card>
        </a-col>

        <!-- 右侧详情面板 -->
        <a-col :span="7" v-if="selectedNode">
          <a-card class="detail-card" :bordered="false">
            <template #title>
              <a-space>
                <FileTextOutlined style="font-size: 18px; color: #52c41a;" />
                <span style="font-size: 16px; font-weight: 600;">节点详情</span>
              </a-space>
            </template>
            <template #extra>
              <CloseOutlined @click="closeDetail" style="cursor: pointer; color: #999;" />
            </template>

            <a-scrollbar style="height: calc(100vh - 280px); overflow: auto;">
              <div class="detail-content">
                <!-- 节点类型标识 -->
                <a-tag 
                  :color="selectedNode.category === 0 ? 'purple' : 'blue'" 
                  style="margin-bottom: 16px; font-size: 14px; padding: 4px 12px;"
                >
                  {{ selectedNode.category === 0 ? '核心专利' : '关联专利' }}
                </a-tag>

                <!-- 专利基本信息 -->
                <a-descriptions :column="1" bordered size="small">
                  <a-descriptions-item label="专利名称">
                    <div style="font-weight: 600; color: #262626; word-break: break-all; line-height: 1.6;">
                      {{ selectedNode.name }}
                    </div>
                  </a-descriptions-item>
                  
                  <a-descriptions-item label="申请号">
                    {{ selectedNode.detail?.applyId || 'CN202310123456.7' }}
                  </a-descriptions-item>
                  
                  <a-descriptions-item label="申请机构">
                    <a-tag color="blue">{{ selectedNode.detail?.applyInstitutionZhName || '未知机构' }}</a-tag>
                  </a-descriptions-item>
                  
                  <a-descriptions-item label="发明人">
                    <a-space wrap>
                      <a-tag 
                        v-for="(inventor, idx) in (selectedNode.detail?.inventors || ['张三', '李四'])" 
                        :key="idx"
                        color="green"
                      >
                        {{ inventor }}
                      </a-tag>
                    </a-space>
                  </a-descriptions-item>
                  
                  <a-descriptions-item label="申请日期">
                    {{ selectedNode.detail?.applyDate || '2023-05-20' }}
                  </a-descriptions-item>
                  
                  <a-descriptions-item label="公开日期">
                    {{ selectedNode.detail?.applyPublicDate || '2023-09-15' }}
                  </a-descriptions-item>
                  
                  <a-descriptions-item label="IPC分类">
                    <a-space wrap>
                      <a-tag 
                        v-for="(ipc, idx) in (selectedNode.detail?.ipcClassId || 'G06F 16/00').split(/[;；]/).filter(i => i.trim())" 
                        :key="idx"
                        color="orange"
                      >
                        {{ ipc.trim() }}
                      </a-tag>
                    </a-space>
                  </a-descriptions-item>
                  
                  <a-descriptions-item label="技术领域">
                    {{ selectedNode.detail?.technology || '计算机技术' }}
                  </a-descriptions-item>
                  
                  <a-descriptions-item label="法律状态">
                    <a-badge 
                      :status="selectedNode.detail?.legalStatus === '有效' ? 'success' : 'default'" 
                      :text="selectedNode.detail?.legalStatus || '有效'"
                    />
                  </a-descriptions-item>
                  
                  <a-descriptions-item label="关联节点数">
                    <span style="font-size: 16px; color: #1890ff; font-weight: 600;">
                      {{ getNodeConnections(selectedNode.id) }} 个
                    </span>
                  </a-descriptions-item>
                </a-descriptions>

                <!-- 摘要信息 -->
                <!-- <a-divider orientation="left" style="margin: 16px 0;">专利摘要</a-divider> -->
                
                <a-divider style="margin: 20px 0 12px 0;" />
                <div style="font-size: 15px; font-weight: 600; color: #262626; margin-bottom: 12px;">
                  专利摘要
                </div>
                <p style="color: #595959; line-height: 1.8; text-align: justify;">
                  {{ selectedNode.detail?.summaryZh || '本发明公开了一种基于人工智能的专利分析方法及系统，通过深度学习技术对专利文本进行语义分析，实现专利的自动分类、关联发现和技术趋势预测。该方法能够有效提高专利分析的效率和准确性，为企业和研究机构的技术创新提供有力支持。' }}
                </p>

                <!-- 操作按钮 -->
                <a-divider style="margin: 16px 0;" />
                <a-space direction="vertical" style="width: 100%;">
                  <a-button 
                    type="primary" 
                    block 
                    @click="setAsCoreNode"
                    :disabled="selectedNode.id === corePatentId"
                  >
                    <template #icon><SyncOutlined /></template>
                    {{ selectedNode.id === corePatentId ? '当前核心节点' : '设为核心节点' }}
                  </a-button>
                  <a-button type="default" block @click="goToPatentManage">
                    <template #icon><EyeOutlined /></template>
                    在专利管理中查看
                  </a-button>
                  <a-button block>
                    <template #icon><ShareAltOutlined /></template>
                    展开关联节点
                  </a-button>
                  <a-button block @click="handleDownloadFile">
                    <template #icon><DownloadOutlined /></template>
                    下载专利文档
                  </a-button>
                </a-space>
      </div>
            </a-scrollbar>
    </a-card>
        </a-col>
      </a-row>
    </div>

    <!-- 右键菜单 (使用 Ant Design Dropdown 组件) -->
    <a-dropdown 
      v-model:open="contextMenu.visible"
      :trigger="[]"
    >
      <div 
        :style="{ 
          position: 'fixed',
          left: contextMenu.x + 'px', 
          top: contextMenu.y + 'px',
          width: '1px',
          height: '1px'
        }"
      ></div>
      <template #overlay>
        <a-menu @click="handleMenuClick">
          <a-menu-item key="setCore">
            <SyncOutlined />
            设为核心节点
          </a-menu-item>
          <a-menu-divider />
          <a-menu-item key="openPatent">
            <FileTextOutlined />
            在专利管理中打开
          </a-menu-item>
          <a-menu-divider />
          <a-menu-item key="copyId">
            <CopyOutlined />
            复制专利ID
          </a-menu-item>
          <a-menu-item key="copyApplyId">
            <CopyOutlined />
            复制申请号
          </a-menu-item>
          <a-menu-item key="copyName">
            <CopyOutlined />
            复制专利名称
          </a-menu-item>
        </a-menu>
      </template>
    </a-dropdown>
  </div>
</template>

<script setup lang="ts" name="patent-analysis-graph-Index">
  import { ref, onMounted, onUnmounted, nextTick, watch } from 'vue';
  import { useRoute } from 'vue-router';
  import { useGo } from '/@/hooks/web/usePage';
  import { useGraphStore } from '/@/store/modules/graph';
  import {
    ApartmentOutlined,
    ClusterOutlined,
    ReloadOutlined,
    FullscreenOutlined,
    FullscreenExitOutlined,
    CameraOutlined,
    FileTextOutlined,
    CloseOutlined,
    EyeOutlined,
    ShareAltOutlined,
    DownloadOutlined,
    SyncOutlined,
    CopyOutlined,
  } from '@ant-design/icons-vue';
  import * as echarts from 'echarts';
  import { message } from 'ant-design-vue';
  
  // 导入图谱API和数据类型
  import { getGraphByPatentId, saveGraphHistory, getLastVisit } from './Graph.api';
  import { transformGraphData } from './Graph.data';
  import { downloadByBase64, downloadByUrl } from '/@/utils/file/download';

  const route = useRoute();
  const go = useGo();
  const graphStore = useGraphStore();

  // 响应式数据
  const corePatentId = ref<string>(''); // 核心专利ID（从URL参数获取）
  const corePatentName = ref<string>(''); // 核心专利名称
  const relationType = ref<string>('institution'); // 关联类型
  const loading = ref<boolean>(false);
  const isFullscreen = ref<boolean>(false);
  const selectedNode = ref<any>(null);
  const graphContainer = ref<HTMLElement | null>(null);
  let chartInstance: echarts.ECharts | null = null;

  // 右键菜单状态
  const contextMenu = ref({
    visible: false,
    x: 0,
    y: 0,
    node: null as any, // 当前右键点击的节点
  });

  // 图谱数据
  const graphData = ref<{
    nodes: any[];
    links: any[];
    categories: any[];
  }>({
    nodes: [],
    links: [],
    categories: [
      { name: '核心专利', itemStyle: { color: '#9254de' } },
      { name: '关联专利', itemStyle: { color: '#1890ff' } },
    ],
  });

  // 生成模拟数据
  const generateMockData = (type: string) => {
    // 核心专利节点（如果有传入专利ID，则使用该ID，否则使用默认值）
    const corePatent = {
      id: corePatentId.value || 'core-1',
      name: corePatentName.value || '基于深度学习的图像识别系统',
      symbolSize: 80,
      category: 0,
      value: 100,
      detail: {
        applicationNo: 'CN202310567890.1',
        institution: '清华大学',
        inventors: ['张伟', '李明', '王芳'],
        applicationDate: '2023-06-15',
        publicationDate: '2023-10-20',
        ipc: 'G06N 3/08',
        technology: '人工智能',
        legalStatus: '有效',
        abstract: '本发明提出了一种基于深度学习的图像识别系统，通过卷积神经网络对图像特征进行提取和分类。该系统采用改进的ResNet架构，结合注意力机制，能够在复杂场景下实现高精度的目标识别。实验结果表明，本系统在标准数据集上的识别准确率达到98.5%，超越了现有主流方法。',
      },
    };

    // 根据不同关联类型生成关联专利
    const relatedPatents: any[] = [];
    const links: any[] = [];

    if (type === 'institution') {
      // 申请机构关联
      const institutions = [
        { name: '清华大学', count: 4, color: '#1890ff' },
        { name: '北京大学', count: 3, color: '#52c41a' },
        { name: '中国科学院', count: 3, color: '#faad14' },
      ];

      institutions.forEach((inst, idx) => {
        for (let i = 0; i < inst.count; i++) {
          const patentId = `patent-${idx}-${i}`;
          relatedPatents.push({
            id: patentId,
            name: `${inst.name}专利${i + 1}`,
            symbolSize: 40 + Math.random() * 20,
            category: 1,
            value: 50 + Math.random() * 50,
            detail: {
              applicationNo: `CN2023${10000000 + Math.floor(Math.random() * 9000000)}.${Math.floor(Math.random() * 10)}`,
              institution: inst.name,
              inventors: ['发明人A', '发明人B'],
              applicationDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`,
              publicationDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`,
              ipc: 'G06F 16/00',
              technology: '计算机技术',
              legalStatus: '有效',
              abstract: `这是一项由${inst.name}申请的专利，涉及相关技术领域的创新研究。`,
            },
          });

          links.push({
            source: corePatent.id,
            target: patentId,
            value: Math.random() * 10,
            label: { show: false },
          });
        }
      });
    } else if (type === 'inventor') {
      // 发明人关联
      const inventors = ['张伟', '李明', '王芳'];
      inventors.forEach((inventor, idx) => {
        for (let i = 0; i < 3; i++) {
          const patentId = `patent-inv-${idx}-${i}`;
          relatedPatents.push({
            id: patentId,
            name: `${inventor}的其他专利${i + 1}`,
            symbolSize: 40 + Math.random() * 20,
            category: 1,
            value: 50 + Math.random() * 50,
            detail: {
              applicationNo: `CN2023${10000000 + Math.floor(Math.random() * 9000000)}.${Math.floor(Math.random() * 10)}`,
              institution: '各类机构',
              inventors: [inventor, '合作发明人'],
              applicationDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`,
              publicationDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`,
              ipc: 'G06N 3/04',
              technology: '神经网络',
              legalStatus: '有效',
              abstract: `这是发明人${inventor}参与的其他专利项目，展示了其在该领域的持续研究。`,
            },
          });

          links.push({
            source: corePatent.id,
            target: patentId,
            value: Math.random() * 10,
            label: { show: false },
          });
        }
      });
    } else if (type === 'ipc') {
      // IPC分类关联
      const ipcCodes = ['G06N 3/08', 'G06N 3/04', 'G06F 16/00'];
      ipcCodes.forEach((ipc, idx) => {
        for (let i = 0; i < 3; i++) {
          const patentId = `patent-ipc-${idx}-${i}`;
          relatedPatents.push({
            id: patentId,
            name: `${ipc}分类专利${i + 1}`,
            symbolSize: 40 + Math.random() * 20,
            category: 1,
            value: 50 + Math.random() * 50,
            detail: {
              applicationNo: `CN2023${10000000 + Math.floor(Math.random() * 9000000)}.${Math.floor(Math.random() * 10)}`,
              institution: '某研究机构',
              inventors: ['研究员A', '研究员B'],
              applicationDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`,
              publicationDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`,
              ipc: ipc,
              technology: 'AI技术',
              legalStatus: '有效',
              abstract: `本专利属于${ipc}分类，代表了该技术领域的创新成果。`,
            },
          });

          links.push({
            source: corePatent.id,
            target: patentId,
            value: Math.random() * 10,
            label: { show: false },
          });
        }
      });
    } else {
      // 技术领域关联
      const technologies = ['人工智能', '机器学习', '计算机视觉'];
      technologies.forEach((tech, idx) => {
        for (let i = 0; i < 3; i++) {
          const patentId = `patent-tech-${idx}-${i}`;
          relatedPatents.push({
            id: patentId,
            name: `${tech}领域专利${i + 1}`,
            symbolSize: 40 + Math.random() * 20,
            category: 1,
            value: 50 + Math.random() * 50,
            detail: {
              applicationNo: `CN2023${10000000 + Math.floor(Math.random() * 9000000)}.${Math.floor(Math.random() * 10)}`,
              institution: '科技公司',
              inventors: ['技术专家', '工程师'],
              applicationDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`,
              publicationDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`,
              ipc: 'G06F 17/00',
              technology: tech,
              legalStatus: '有效',
              abstract: `这是${tech}领域的一项创新专利，展示了该领域的最新研究进展。`,
            },
          });

          links.push({
            source: corePatent.id,
            target: patentId,
            value: Math.random() * 10,
            label: { show: false },
          });
        }
      });
    }

    return {
      nodes: [corePatent, ...relatedPatents],
      links: links,
    };
  };

  // 加载图谱数据
  const loadGraphData = async () => {
    loading.value = true;
    try {
      // 如果没有核心专利ID，使用模拟数据
      if (!corePatentId.value) {
        console.warn('未指定核心专利ID，使用模拟数据');
        const mockData = generateMockData(relationType.value);
        graphData.value.nodes = mockData.nodes;
        graphData.value.links = mockData.links;
        
        await nextTick();
        initChart();
        message.success('数据加载成功（模拟数据）');
        loading.value = false;
        return;
      }

      // 调用后端API获取图谱数据
      console.log('正在从后端加载图谱数据...', {
        patent_id: corePatentId.value,
        type: relationType.value
      });
      
      const response = await getGraphByPatentId(
        corePatentId.value,  // patent_id
        relationType.value,  // type
        20                   // maxNodes
      );
      
      console.log('后端响应数据:', response);
      
      // 兼容两种响应格式：
      // 1. JeecG框架格式: { success: true, result: [...] }
      // 2. axios解包后的格式: 直接是数组 [...]
      let graphList;
      if (Array.isArray(response)) {
        // 直接是数组，说明axios已经解包了result
        graphList = response;
      } else if (response.success && response.result) {
        // 标准JeecG格式
        graphList = response.result;
      } else {
        throw new Error(response.message || '数据加载失败');
      }
      
      // 转换后端数据为前端格式
      const transformedData = transformGraphData({ 
        success: true, 
        message: '操作成功',
        result: graphList 
      });
      
      graphData.value.nodes = transformedData.nodes;
      graphData.value.links = transformedData.links;
      graphData.value.categories = transformedData.categories;
      
      // 更新核心专利名称
      if (transformedData.nodes.length > 0) {
        corePatentName.value = transformedData.nodes[0].name;
      }
      
      await nextTick();
      initChart();
      message.success('数据加载成功');
      
      // 保存访问记录（后端会自动获取当前登录用户）
      try {
        if (corePatentId.value) {
          await saveGraphHistory(
            corePatentId.value,
            corePatentName.value,
            relationType.value
          );
          console.log('访问记录已保存');
        }
      } catch (error) {
        console.error('保存访问记录失败:', error);
        // 静默失败，不影响主流程
      }
    } catch (error: any) {
      console.error('加载图谱数据失败:', error);
      
      // 如果API调用失败，降级使用模拟数据
      message.warning('从服务器加载失败，使用模拟数据展示');
      const mockData = generateMockData(relationType.value);
      graphData.value.nodes = mockData.nodes;
      graphData.value.links = mockData.links;
      
      await nextTick();
      initChart();
    } finally {
      loading.value = false;
    }
  };

  // 初始化图谱
  const initChart = () => {
    if (!graphContainer.value) return;

    // 销毁已存在的实例
    if (chartInstance) {
      chartInstance.dispose();
    }

    chartInstance = echarts.init(graphContainer.value);

    const option = {
      title: {
        show: graphData.value.nodes.length === 0,
        text: '暂无数据',
        left: 'center',
        top: 'center',
        textStyle: {
          color: '#999',
          fontSize: 16,
        },
      },
      tooltip: {
        trigger: 'item',
        formatter: (params: any) => {
          if (params.dataType === 'node') {
            return `
              <div style="padding: 8px;">
                <strong style="font-size: 14px; color: #262626;">${params.data.name}</strong><br/>
                <div style="margin-top: 6px; color: #595959;">
                  <span style="color: #1890ff;">●</span> 申请机构: ${params.data.detail?.institution || '未知'}<br/>
                  <span style="color: #52c41a;">●</span> 关联度: ${params.data.value.toFixed(1)}
                </div>
              </div>
            `;
          }
          return params.data.source + ' → ' + params.data.target;
        },
      },
      legend: [
        {
          data: graphData.value.categories.map((c) => c.name),
          orient: 'vertical',
          left: 10,
          top: 20,
          itemGap: 12,
          textStyle: {
            fontSize: 12,
            color: '#595959',
          },
        },
      ],
      animationDuration: 1500,
      animationEasingUpdate: 'quinticInOut' as any,
      series: [
        {
          type: 'graph',
          layout: 'force',
          data: graphData.value.nodes,
          links: graphData.value.links,
          categories: graphData.value.categories,
          roam: true,
          label: {
            show: true,
            position: 'inside',
            color: '#ffffff',
            lineHeight: 18,
            fontSize: 12,
            textBorderColor: 'rgba(0, 0, 0, 0.45)',
            textBorderWidth: 2,
            textShadowColor: 'rgba(0, 0, 0, 0.35)',
            textShadowBlur: 6,
            backgroundColor: 'rgba(38, 38, 38, 0.35)',
            borderRadius: 6,
            padding: [4, 6, 4, 6],
            formatter: function(params: any): string {
              const name = params.name || '';
              const maxLength = params.data?.labelMaxChars || 8;
              if (name.length <= maxLength) {
                return name;
              }
              const lines: string[] = [];
              for (let i = 0; i < name.length; i += maxLength) {
                lines.push(name.substring(i, i + maxLength));
              }
              return lines.join('\n');
            },
          },
          emphasis: {
            focus: 'adjacency',
            label: {
              fontSize: 13,
            },
            lineStyle: {
              width: 3,
            },
          },
          force: {
            repulsion: 900,
            edgeLength: [220, 280],
            gravity: 0.05,
            friction: 0.55,
            layoutAnimation: true,
          },
          lineStyle: {
            color: '#b37feb',
            curveness: 0,
            opacity: 0.7,
            width: 2,
          },
          edgeSymbol: ['none', 'arrow'],
          edgeSymbolSize: [0, 10],
        },
      ],
    };

    chartInstance.setOption(option);

    // 节点点击事件
    chartInstance.on('click', (params: any) => {
      if (params.dataType === 'node') {
        selectedNode.value = params.data;
        
        // 高亮选中的节点
        chartInstance?.dispatchAction({
          type: 'highlight',
          seriesIndex: 0,
          dataIndex: params.dataIndex,
        });
      }
    });

    // 节点右键事件
    chartInstance.on('contextmenu', (params: any) => {
      if (params.dataType === 'node') {
        // 阻止默认右键菜单
        params.event.event.preventDefault();
        
        // 保存右键点击的节点
        contextMenu.value.node = params.data;
        
        // 计算菜单位置
        const event = params.event.event;
        contextMenu.value.x = event.clientX;
        contextMenu.value.y = event.clientY;
        contextMenu.value.visible = true;
      }
    });

    // 监听窗口大小变化
    window.addEventListener('resize', handleResize);
  };

  // 处理窗口大小变化
  const handleResize = () => {
    chartInstance?.resize();
  };

  // 全屏切换
  const toggleFullscreen = () => {
    isFullscreen.value = !isFullscreen.value;
    nextTick(() => {
      chartInstance?.resize();
    });
  };

  // 导出图片
  const exportImage = () => {
    if (!chartInstance) {
      message.warning('请先加载图谱数据');
      return;
    }

    const url = chartInstance.getDataURL({
      type: 'png',
      pixelRatio: 2,
      backgroundColor: '#fff',
    });

    const link = document.createElement('a');
    link.download = `专利图谱_${new Date().getTime()}.png`;
    link.href = url;
    link.click();
    message.success('图片导出成功');
  };

  // 下载专利文档
  const handleDownloadFile = () => {
    if (!selectedNode.value) {
      message.warning('请先选择一个专利节点');
      return;
    }

    const fileString = selectedNode.value.detail?.fileString;
    if (!fileString || fileString.trim() === '') {
      message.warning('该专利暂无可下载的文档');
      return;
    }

    try {
      const patentName = selectedNode.value.name || '专利文档';
      const applyId = selectedNode.value.detail?.applyId || new Date().getTime();
      const fileName = `${patentName}_${applyId}.pdf`;

      if (/^https?:\/\//i.test(fileString)) {
        downloadByUrl({ url: fileString, fileName, target: '_self' });
        message.success('文档下载已开始');
        return;
      }

      const normalized = fileString.trim();
      const dataUrl = normalized.startsWith('data:') ? normalized : `data:application/pdf;base64,${normalized}`;
      downloadByBase64(dataUrl, fileName, 'application/pdf');
      message.success('文档下载成功');
    } catch (error) {
      console.error('下载文档失败:', error);
      message.error('文档下载失败，请检查文档格式');
    }
  };

  // 关闭详情面板
  const closeDetail = () => {
    selectedNode.value = null;
    
    // 延迟调整图谱大小，等待 DOM 更新
    nextTick(() => {
      setTimeout(() => {
        chartInstance?.resize();
      }, 300);
    });
    
    // 取消高亮
    chartInstance?.dispatchAction({
      type: 'downplay',
      seriesIndex: 0,
    });
  };

  // 获取节点连接数
  const getNodeConnections = (nodeId: string) => {
    if (!nodeId) return 0;
    
    return graphData.value.links.filter((link) => {
      // ECharts 可能将 source/target 转换为索引或对象
      const sourceId = typeof link.source === 'object' ? link.source.id : link.source;
      const targetId = typeof link.target === 'object' ? link.target.id : link.target;
      return sourceId === nodeId || targetId === nodeId;
    }).length;
  };

  // 监听关联类型变化
  watch(relationType, () => {
    if (graphData.value.nodes.length > 0) {
      loadGraphData();
    }
  });

  // 监听节点选择变化，调整图谱大小
  watch(selectedNode, () => {
    // 延迟调整大小，等待 DOM 更新完成
    nextTick(() => {
      setTimeout(() => {
        chartInstance?.resize();
      }, 300);
    });
  });

  // 跳转到专利管理页面
  const goToPatentManage = () => {
    // 如果有选中的节点，自动打开详情
    if (selectedNode.value && selectedNode.value.id) {
      graphStore.setCurrentPatent(selectedNode.value.id, selectedNode.value.name);
      graphStore.setAutoOpenDetail(true);  // 标记需要自动打开详情
    }
    go('/patent/patent/patentList');
  };

  // 设置为核心节点
  const setAsCoreNode = () => {
    if (!selectedNode.value || !selectedNode.value.id) {
      message.warning('请先选择一个节点');
      return;
    }

    if (selectedNode.value.id === corePatentId.value) {
      message.info('该节点已经是核心节点');
      return;
    }

    // 更新核心专利信息
    const newCoreId = selectedNode.value.id;
    const newCoreName = selectedNode.value.name;

    message.loading({ content: `正在切换到核心节点: ${newCoreName}...`, key: 'switchCore' });

    // 更新状态
    corePatentId.value = newCoreId;
    corePatentName.value = newCoreName;

    // 更新 Pinia Store
    graphStore.setCurrentPatent(newCoreId, newCoreName);

    // 关闭详情面板（可选）
    selectedNode.value = null;

    // 重新加载图谱数据
    loadGraphData();

    message.success({ content: `已切换到核心节点: ${newCoreName}`, key: 'switchCore' });
  };

  // 监听 Pinia Store 中的专利ID变化
  watch(() => graphStore.getCurrentPatentId, (newPatentId) => {
    if (newPatentId && newPatentId !== corePatentId.value) {
      console.log('[GraphStore] 检测到新专利ID:', newPatentId);
      corePatentId.value = newPatentId;
      corePatentName.value = graphStore.getCurrentPatentName;
      message.success(`已切换到专利: ${graphStore.getCurrentPatentName || newPatentId}`);
      // 重新加载数据
      loadGraphData();
    }
  });

  // 处理全局点击事件，点击菜单外部时关闭菜单
  const handleGlobalClick = () => {
    // 如果菜单是打开的，则关闭菜单
    if (contextMenu.value.visible) {
      contextMenu.value.visible = false;
      contextMenu.value.node = null;
    }
  };

  // 复制到剪贴板的通用函数
  const copyToClipboard = (text: string, label: string) => {
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(text).then(() => {
        message.success(`已复制${label}: ${text}`);
      }).catch(() => {
        message.error('复制失败');
      });
    } else {
      // 兼容旧浏览器
      const textarea = document.createElement('textarea');
      textarea.value = text;
      textarea.style.position = 'fixed';
      textarea.style.opacity = '0';
      document.body.appendChild(textarea);
      textarea.select();
      try {
        document.execCommand('copy');
        message.success(`已复制${label}: ${text}`);
      } catch (err) {
        message.error('复制失败');
      }
      document.body.removeChild(textarea);
    }
  };

  // 统一的右键菜单处理函数
  const handleMenuClick = ({ key }: { key: string }) => {
    if (!contextMenu.value.node) return;
    
    const node = contextMenu.value.node;
    
    // 先关闭菜单
    contextMenu.value.visible = false;
    
    switch (key) {
      case 'setCore':
        // 设为核心节点
        if (node.id === corePatentId.value) {
          message.info('该节点已经是核心节点');
          return;
        }
        
        message.loading({ content: `正在切换到核心节点: ${node.name}...`, key: 'switchCore' });
        corePatentId.value = node.id;
        corePatentName.value = node.name;
        graphStore.setCurrentPatent(node.id, node.name);
        loadGraphData();
        message.success({ content: `已切换到核心节点: ${node.name}`, key: 'switchCore' });
        break;
        
      case 'openPatent':
        // 在专利管理中打开，并设置自动打开详情标记
        graphStore.setCurrentPatent(node.id, node.name);
        graphStore.setAutoOpenDetail(true);  // 标记需要自动打开详情
        go('/patent/patent/patentList');
        break;
        
      case 'copyId':
        // 复制专利ID
        copyToClipboard(node.id, '专利ID');
        break;
        
      case 'copyApplyId':
        // 复制申请号
        const applyId = node.detail?.applyId || '暂无申请号';
        copyToClipboard(applyId, '申请号');
        break;
        
      case 'copyName':
        // 复制专利名称
        copyToClipboard(node.name, '专利名称');
        break;
    }
    
    // 清空节点引用
    contextMenu.value.node = null;
  };

  // 组件挂载
  onMounted(async () => {
    // 添加全局点击监听器，用于关闭右键菜单
    document.addEventListener('click', handleGlobalClick);

    // 优先从 Pinia Store 获取专利ID（从专利列表跳转过来的情况）
    const storePatentId = graphStore.getCurrentPatentId;
    if (storePatentId) {
      corePatentId.value = storePatentId;
      corePatentName.value = graphStore.getCurrentPatentName;
      message.success(`已选择专利: ${graphStore.getCurrentPatentName || storePatentId}`);
      // 自动加载数据
      loadGraphData();
      return;
    }
    
    // 其次从URL参数获取专利ID（兼容旧的跳转方式）
    const patentId = route.query.patentId as string;
    if (patentId) {
      corePatentId.value = patentId;
      message.success(`已选择专利ID: ${patentId} 作为核心节点`);
      // 自动加载数据
      loadGraphData();
      return;
    }
    
    // 如果URL没有专利ID，则尝试加载上次访问记录（后端会自动获取当前登录用户）
    try {
      console.log('正在加载上次访问记录...');
      const lastVisit = await getLastVisit();
      
      if (lastVisit && lastVisit.patentId) {
        corePatentId.value = lastVisit.patentId;
        corePatentName.value = lastVisit.patentName || '';
        relationType.value = lastVisit.relationType || 'institution';
        
        message.info(`已加载上次访问的专利: ${lastVisit.patentName || lastVisit.patentId}`);
        
        // 自动加载数据
        loadGraphData();
      } else {
        console.log('未找到历史访问记录，等待用户选择专利');
      }
    } catch (error) {
      console.error('加载历史记录失败:', error);
      // 静默失败，不影响用户使用
    }
  });


  // 组件卸载
  onUnmounted(() => {
    if (chartInstance) {
      chartInstance.dispose();
      chartInstance = null;
    }
    window.removeEventListener('resize', handleResize);
    document.removeEventListener('click', handleGlobalClick);
  });
</script>

<style scoped lang="less">
.graph-container {
  padding: 20px;
  background: #f0f2f5;
  min-height: calc(100vh - 100px);
  position: relative;

  // 页面头部卡片
  .header-card {
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    background: #fff;

    :deep(.ant-card-body) {
      padding: 20px 24px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .page-title {
      font-size: 20px;
      font-weight: 600;
      color: #262626;
      line-height: 1.4;
    }

    .page-subtitle {
      font-size: 14px;
      color: #8c8c8c;
      margin-top: 4px;
    }
  }

  // 图谱主区域
  .graph-main {
    margin-top: 16px;
    transition: all 0.3s ease;

    &.fullscreen {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 9999;
      background: #f0f2f5;
      padding: 20px;
      margin: 0;
    }
  }

  // 图谱卡片
  .graph-card {
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    background: #fff;

    :deep(.ant-card-head) {
      border-bottom: 1px solid #f0f0f0;
      padding: 16px 24px;
    }

    :deep(.ant-card-body) {
      padding: 24px;
      min-height: calc(100vh - 240px);
    }

    .graph-content {
      width: 100%;
      height: calc(100vh - 280px);
      position: relative;
    }
  }

  // 详情卡片
  .detail-card {
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    background: #fff;
    animation: slideIn 0.3s ease;

    :deep(.ant-card-head) {
      border-bottom: 1px solid #f0f0f0;
      padding: 16px 24px;
    }

    :deep(.ant-card-body) {
      padding: 24px;
    }

    .detail-content {
      :deep(.ant-descriptions-item-label) {
        font-weight: 500;
        color: #595959;
        background: #fafafa;
        white-space: nowrap;  // 标签列不换行
        width: 80px;          // 固定宽度
      }

      :deep(.ant-descriptions-item-content) {
        color: #262626;
        word-break: break-all;     // 内容列自动换行
        word-wrap: break-word;
      }

      :deep(.ant-divider-inner-text) {
        font-weight: 600;
        color: #262626;
      }
    }
  }

  @keyframes slideIn {
    from {
      opacity: 0;
      transform: translateX(20px);
    }
    to {
      opacity: 1;
      transform: translateX(0);
    }
  }
}

// 全局样式调整
:deep(.ant-tag) {
  border-radius: 4px;
  padding: 2px 8px;
}

:deep(.ant-btn) {
  border-radius: 6px;
  transition: all 0.3s ease;

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }
}

:deep(.ant-select-selector) {
  border-radius: 6px !important;
}
</style>

